package com.franklin.java.api.annotation;


import com.franklin.java.api.mybatis.annotation.MyBatisAnnotations;
import com.franklin.java.api.mybatis.mybatisplus.annotation.MPAnnotations;
import com.franklin.java.api.spring.annotation.bean.BeanAnnotations;
import com.franklin.java.api.spring.annotation.bean.DependencyInjectionAnnotations;
import com.intellij.psi.PsiAnnotation;
import org.jetbrains.annotations.NotNull;

import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author Franklin
 * @since 2021/8/13 12:28
 */
public abstract class BaseAnnotation {

    public static void initialize(){
        try {
            Class.forName(DependencyInjectionAnnotations.class.getName());
            Class.forName(BeanAnnotations.class.getName());
            Class.forName(MyBatisAnnotations.class.getName());
            Class.forName(MPAnnotations.class.getName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    protected static final AnnotationMap annotationMap = new AnnotationMap();

    protected String qualifiedName;
    protected String shortName;

    protected PsiAnnotation psiAnnotation;

    public PsiAnnotation getPsiAnnotation() {
        return psiAnnotation;
    }

    public String getQualifiedName() {
        return qualifiedName;
    }

    public String getShortName() {
        return shortName;
    }

    public BaseAnnotation(String qualifiedName, String shortName) {
        this.qualifiedName = qualifiedName;
        this.shortName = shortName;
    }

    public static <E extends BaseAnnotation> E parse(PsiAnnotation psiAnnotation,Class<E> annType){
        String qualifiedName = psiAnnotation.getQualifiedName();
        BaseAnnotation baseAnnotation = annotationMap.get(qualifiedName);
        if (Objects.nonNull(baseAnnotation)){
            baseAnnotation.psiAnnotation = psiAnnotation;
            return (E)baseAnnotation;
        }
        return null;
    }

    public static <E extends BaseAnnotation> E get(Class<E> type){
        return (E) annotationMap.typeAnnMap.get(type);
    }

    protected static class AnnotationMap extends ConcurrentHashMap<String,BaseAnnotation>{

        private ConcurrentHashMap<Class,BaseAnnotation> typeAnnMap = new ConcurrentHashMap<>();

        public BaseAnnotation put(@NotNull BaseAnnotation baseAnnotation) {
            typeAnnMap.put(baseAnnotation.getClass(),baseAnnotation);
            return super.put(baseAnnotation.getQualifiedName(), baseAnnotation);
        }
    }

}
